package com.heima.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.common.exception.CustomException;
import com.heima.feigns.article.ArticleFeign;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.pojos.ApAuthor;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.model.search.vo.SearchArticleVo;
import com.heima.model.utils.threadlocal.AppThreadLocalUtils;
import com.heima.search.service.ApUserSearchService;
import com.heima.search.service.ArticleSearchService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;


@Service
@Slf4j
public class ArticleSearchServiceimpl implements ArticleSearchService {

    @Resource
    RestHighLevelClient restHighLevelClient;

    @Resource
    ArticleFeign articleFeign;

    @Resource
    ApUserSearchService apUserSearchService;
    @Override
    public ResponseResult search(UserSearchDto dto) {
        //参数校验
        if (dto == null || StringUtils.isBlank(dto.getSearchWords())) {
            throw new CustomException(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        if (dto.getMinBehotTime() == null) {
            dto.setMinBehotTime(new Date());
        }

        if (dto.getPageSize() == 0) {
            dto.setPageSize(10);
        }

        SearchRequest request = new SearchRequest("app_info_article");

        SearchSourceBuilder builder = new SearchSourceBuilder();

        BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
        //条件查询
        queryBuilder.must(QueryBuilders.matchQuery("title", dto.getSearchWords()));
        queryBuilder.filter(QueryBuilders.rangeQuery("publishTime").lt(dto.getMinBehotTime()));
        builder.query(queryBuilder);
        //分页
        builder.from(dto.getPageNum());
        builder.size(dto.getPageSize());
        //高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        highlightBuilder.preTags("<font style='color:red'>");
        highlightBuilder.postTags("</font>");
        builder.highlighter(highlightBuilder);
        //查询
        request.source(builder);

        //异步添加搜索记录
        dto.setEquipmentId(AppThreadLocalUtils.getUser().getId());
        apUserSearchService.insert(dto);

        ArrayList<SearchArticleVo> searchArticleVos = new ArrayList<>();
        try {
            SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            SearchHits hits = response.getHits();
            SearchHit[] searchHits = hits.getHits();
            //遍历结果集
            for (SearchHit searchHit : searchHits) {
                //把查询结果转为searchArticleVo对象
                String searchArticleVoJson = searchHit.getSourceAsString();
                SearchArticleVo searchArticleVo = JSON.parseObject(searchArticleVoJson, SearchArticleVo.class);
                //获取高亮的数据
                HighlightField highlightField = searchHit.getHighlightFields().get("title");
                Text[] fragments = highlightField.getFragments();
                String noto = StringUtils.join(fragments);
                //重新赋值
                searchArticleVo.setTitle(noto);
                searchArticleVos.add(searchArticleVo);
            }

        } catch (IOException e) {
            log.error("search result error:{} ", e);
            e.printStackTrace();
        }
        return ResponseResult.okResult(searchArticleVos);
    }

    @Override
    public void saveArticle(String articleId, SearchArticleVo article) {
        //参数校验
        if (StringUtils.isBlank(articleId) || article == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        ApArticle apArticle = articleFeign.findByArticleId(Long.valueOf(articleId));
        //判断mysql数据库是否存在数据
        if (apArticle != null) {
            //有数据同步到es中
            IndexRequest indexRequest = new IndexRequest("app_info_article");
            indexRequest.source(JSON.toJSONString(article), XContentType.JSON);

            try {
                restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
            } catch (IOException e) {
                log.error("es添加数据失败===>{}", e);
                e.printStackTrace();
            }
        }


    }

    @Override
    public void deleteArticle(String articleId) {
        //参数校验
        if (StringUtils.isBlank(articleId)) {
            throw new CustomException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //删除
        DeleteRequest request = new DeleteRequest("app_info_article");
        request.id(articleId);
        try {
            restHighLevelClient.delete(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("es删除数据失败===>", e);
            e.printStackTrace();
        }

    }
}
